﻿using Dapper;
using Dapper.Contrib.Extensions;
using HSJM.Service.MWS.Infrastructure.Dapper;
using HSJM.Service.MWS.Utility;
using HSJM.Service.MWS.Utility.Logs;
using Microsoft.AspNetCore.Http;
using Microsoft.AspNetCore.Mvc.Rendering;
using Microsoft.IdentityModel.Tokens;
using System;
using System.Collections.Generic;
using System.Data;
using System.Linq;
using System.Reflection;
using System.Security.Claims;
using System.Text;
using System.Text.Json.Serialization;
using System.Threading.Tasks;
using System.Web;
using Ubiety.Dns.Core;
using Newtonsoft.Json;
using Org.BouncyCastle.Utilities.Collections;

namespace HSJM.Service.MWS.Infrastructure.Repositories
{
    /// <summary>
    /// 泛型Repository
    /// </summary>
    /// <typeparam name="T"></typeparam>
    public class Repository<T> : IRepository<T> where T : class, IEntity
    {
        private IUnitOfWork _unitOfWork;
        private static IHttpContextAccessor _accessor;

        public Repository(IUnitOfWork unitOfWork, IHttpContextAccessor accessor)
        {
            _unitOfWork = unitOfWork;
            _accessor = accessor;
        }

        /// <summary>
        /// 获取事物
        /// </summary>
        /// <returns></returns>
        public IDbTransaction GetTransaction()
        {
            _unitOfWork.BeginTransaction();
            return _unitOfWork.DbTransaction;
        }


        #region 查询

        /// <summary>
        /// 查询
        /// </summary>
        /// <typeparam name="T"></typeparam>
        /// <param name="sql"></param>
        /// <param name="param"></param>
        /// <param name="commandType"></param>
        /// <returns></returns>
        public IEnumerable<T> GetList(string sql = null, object param = null, CommandType? commandType = null)
        {
            if (sql == null)
            {
                sql = @"Select * from " + SQLLib.GetTableName(typeof(T));
                sql += " Where 1=1 ";
                sql += " AND IsDeleted=0 ";
            }
            var r = _unitOfWork.DbConnection.Query<T>(sql, param: param, transaction: _unitOfWork.DbTransaction, commandType: commandType);
            return r;
        }

        /// <summary>
        /// 查询集合
        /// </summary>
        /// <typeparam name="T"></typeparam>
        /// <param name="sql"></param>
        /// <param name="param"></param>
        /// <param name="commandType"></param>
        /// <returns></returns>
        public async Task<IEnumerable<T>> GetListAsync(object param = null, string sql = null, CommandType? commandType = null)
        {
            try
            {
                if (sql == null)
                {
                    sql = @"Select * from " + SQLLib.GetTableName(typeof(T));
                    sql += " Where 1=1 ";
                    sql += " AND IsDeleted=0 ";
                }
                if (param != null)
                {
                    foreach (var item in param.GetType().GetProperties())
                    {
                        var val = item.GetValue(param);
                        if (val != null)
                        {
                            sql += $" AND {item.Name} = @{item.Name} ";
                        }
                    }
                }
                var r = await _unitOfWork.DbConnection.QueryAsync<T>(sql, param: param, transaction: _unitOfWork.DbTransaction, commandType: commandType).ConfigureAwait(false);
                return r;
            }
            catch (Exception ex)
            {
                MyLogger.Logger.Error(ex.Message);
                return default(IEnumerable<T>);
            }

        }

        /// <summary>
        /// 查询集合
        /// </summary>
        /// <param name="sqlStr">条件</param>
        /// <returns></returns>
        public async Task<IEnumerable<T>> GetListAsync(string sqlStr) {
            var sql = "";
            sql = @"Select * from " + SQLLib.GetTableName(typeof(T));
            sql += " Where 1=1 ";
            sql += " AND IsDeleted=0 ";
            if (!string.IsNullOrEmpty(sqlStr))
            {
                sql += sqlStr;
            }
            var r = await _unitOfWork.DbConnection.QueryAsync<T>(sql,  transaction: _unitOfWork.DbTransaction).ConfigureAwait(false);
            return r;
        }



        /// <summary>
        /// 获取行数据
        /// </summary>
        /// <typeparam name="T"></typeparam>
        /// <param name="id"></param>
        /// <returns></returns>
        public T Get(object id)
        {
            var r = _unitOfWork.DbConnection.Get<T>(id, _unitOfWork.DbTransaction);
            return r;
        }

        /// <summary>
        /// 根据ID获取（异步）
        /// </summary>
        /// <param name="id"></param>
        /// <returns></returns>
        public async Task<T> GetAsync(object id)
        {
            var r = await _unitOfWork.DbConnection.GetAsync<T>(id.ToString(), _unitOfWork.DbTransaction).ConfigureAwait(false);
            return r;
        }

        /// <summary>
        /// 分页方法
        /// </summary>
        /// <param name="pageIndex"></param>
        /// <param name="pageSize"></param>
        /// <param name="sql"></param>
        /// <param name="param"></param>
        /// <returns></returns>
        public PagedResult<T> GetPageList(int pageIndex, int pageSize, string sql = null, object param = null)
        {
            if (sql == null)
            {
                sql = @"Select * from " + SQLLib.GetTableName(typeof(T));
                sql += " Where 1=1 ";
                sql += " AND IsDeleted=0 ";
            }
            if (param != null)
            {
                foreach (var item in param.GetType().GetProperties())
                {
                    var val = item.GetValue(param);
                    if (val != null)
                    {
                        sql += $" AND {item.Name} = @{item.Name} ";
                    }
                }
            }
            var pagingResult = _unitOfWork.DbConnection.GetPageList<T>(sql, pageIndex, pageSize, param: param, transaction: _unitOfWork.DbTransaction);
            return pagingResult;
        }
        #endregion

        #region 删除
        /// <summary>
        /// 删除行数据
        /// </summary>
        /// <param name="entity"></param>
        /// <param name="isDel">是否硬删除（默认软删除）</param>
        /// <param name="dbTransaction"></param>
        /// <returns></returns>
        public bool Delete(T entity, bool isDel = false, IDbTransaction dbTransaction = null)
        {
            if (isDel)
            {
                var r = _unitOfWork.DbConnection.Delete<T>(entity, dbTransaction == null ? _unitOfWork.DbTransaction : dbTransaction);

                return r;
            }
            else
            {
                var baseEntity = entity.GetType().GetProperties();
                foreach (var item in baseEntity)
                {
                    if (item.Name == "IsDeleted")
                    {
                        var val = true;
                        item.SetValue(entity, val);
                        break;
                    }
                }
                var r = _unitOfWork.DbConnection.Update<T>(entity, dbTransaction == null ? _unitOfWork.DbTransaction : dbTransaction);
                return r;
            }
        }

        /// <summary>
        /// 删除(异步)
        /// </summary>
        /// <param name="entity"></param>
        /// <param name="isDel">是否硬删除（默认软删除）</param>
        /// <param name="dbTransaction"></param>
        /// <returns></returns>
        public async Task<bool> DeleteAsync(T entity, bool isDel = false, IDbTransaction dbTransaction = null)
        {
            if (entity==null)
            {
                return false;
            }
            if (isDel)
            {
                var r = await _unitOfWork.DbConnection.DeleteAsync<T>(entity, dbTransaction == null ? _unitOfWork.DbTransaction : dbTransaction).ConfigureAwait(false);

                return r;
            }
            else
            {
                var baseEntity = entity.GetType().GetProperties();
                foreach (var item in baseEntity)
                {
                    if (item.Name == "IsDeleted")
                    {
                        var val = true;
                        item.SetValue(entity, val);
                        break;
                    }
                }
                var r = await _unitOfWork.DbConnection.UpdateAsync<T>(entity, dbTransaction == null ? _unitOfWork.DbTransaction : dbTransaction).ConfigureAwait(false);
                return r;
            }
        }

        /// <summary>
        /// 删除表所有数据
        /// </summary>
        /// <typeparam name="T"></typeparam>
        /// <returns></returns>
        public Task<bool> DeleteAll()
        {
            var r = _unitOfWork.DbConnection.DeleteAllAsync<T>(_unitOfWork.DbTransaction);
            return r;
        }

        /// <summary>
        /// 删除所有（异步）
        /// </summary>
        /// <returns></returns>
        public async Task<bool> DeleteAllAsync()
        {
            var r = await _unitOfWork.DbConnection.DeleteAllAsync<T>(_unitOfWork.DbTransaction).ConfigureAwait(false);
            return r;
        }

        #endregion

        #region 新增

        /// <summary>
        /// 添加行数据
        /// </summary>
        /// <typeparam name="T"></typeparam>
        /// <param name="entity"></param>
        /// <returns></returns>
        public long Insert(T entity, IDbTransaction dbTransaction = null)
        {
            if (entity != null)
            {
                var baseEntity = entity.GetType().GetProperties();
                var accountInfo = _accessor.HttpContext.Request.Headers["AccountInfo"].ToString();//.FindFirst(ClaimTypes.NameIdentifier)?.Value;
                accountInfo = HttpUtility.UrlDecode(accountInfo);
                var header = JsonConvert.DeserializeObject<CustomHeader>(accountInfo);
                foreach (var item in baseEntity)
                {
                    if (item.Name == "IsDeleted")
                    {
                        var val = false;
                        item.SetValue(entity, val);
                    }
                    else if (item.Name == "CreaterId")
                    {
                        var val = header?.Id;
                        item.SetValue(entity, val);
                    }
                    else if (item.Name == "CreateTime")
                    {
                        var val = DateTime.Now;
                        item.SetValue(entity, val);
                    }
                    else if (item.Name == "ModifierId")
                    {
                        var val = header?.Id;
                        item.SetValue(entity, val);
                    }
                    else if (item.Name == "ModifyTime")
                    {
                        var val = DateTime.Now;
                        item.SetValue(entity, val);
                    }
                    else if (item.Name == "CreaterName")
                    {
                        var val = header?.UserName;
                        item.SetValue(entity, val);
                    }
                    else if (item.Name == "ModifierName")
                    {
                        var val = header?.UserName;
                        item.SetValue(entity, val);
                    }
                }
            }
            var r = _unitOfWork.DbConnection.Insert<T>(entity, dbTransaction == null ? _unitOfWork.DbTransaction : dbTransaction);
            return r;

        }

        /// <summary>
        /// 插入单个数据（异步）
        /// </summary>
        /// <param name="entity"></param>
        /// <param name="dbTransaction"></param>
        /// <returns></returns>
        public async Task<int> InsertAsync(T entity, IDbTransaction dbTransaction = null)
        {
            if (entity != null)
            {
                var baseEntity = entity.GetType().GetProperties();
                var accountInfo = _accessor.HttpContext.Request.Headers["AccountInfo"].ToString();//.FindFirst(ClaimTypes.NameIdentifier)?.Value;
                accountInfo = HttpUtility.UrlDecode(accountInfo);
                var header = JsonConvert.DeserializeObject<CustomHeader>(accountInfo);
                foreach (var item in baseEntity)
                {
                    if (item.Name == "IsDeleted")
                    {
                        var val = false;
                        item.SetValue(entity, val);
                    }
                    else if (item.Name == "CreaterId")
                    {
                        var val = header?.Id;
                        item.SetValue(entity, val);
                    }
                    else if (item.Name == "CreateTime")
                    {
                        var val = DateTime.Now;
                        item.SetValue(entity, val);
                    }
                    else if (item.Name == "ModifierId")
                    {
                        var val = header?.Id;
                        item.SetValue(entity, val);
                    }
                    else if (item.Name == "ModifyTime")
                    {
                        var val = DateTime.Now;
                        item.SetValue(entity, val);
                    }
                    else if (item.Name == "CreaterName")
                    {
                        var val = header?.UserName;
                        item.SetValue(entity, val);
                    }
                    else if (item.Name == "ModifierName")
                    {
                        var val = header?.UserName;
                        item.SetValue(entity, val);
                    }
                }
            }
            var r = await _unitOfWork.DbConnection.InsertAsync<T>(entity, dbTransaction == null ? _unitOfWork.DbTransaction : dbTransaction).ConfigureAwait(false);
            return r;
        }


        #endregion

        #region 修改

        /// <summary>
        /// 更新行数据
        /// </summary>
        /// <typeparam name="T"></typeparam>
        /// <param name="entity"></param>
        /// <returns></returns>
        public bool Update(T entity, IDbTransaction dbTransaction = null)
        {
            if (entity != null)
            {
                var baseEntity = entity.GetType().GetProperties();
                var accountInfo = _accessor.HttpContext.Request.Headers["AccountInfo"].ToString();//.FindFirst(ClaimTypes.NameIdentifier)?.Value;
                accountInfo = HttpUtility.UrlDecode(accountInfo);
                var header = JsonConvert.DeserializeObject<CustomHeader>(accountInfo);
                foreach (var item in baseEntity)
                {
                    if (item.Name == "ModifierId")
                    {
                        var val = header?.Id;
                        item.SetValue(entity, val);
                    }
                    else if (item.Name == "ModifyTime")
                    {
                        var val = DateTime.Now;
                        item.SetValue(entity, val);
                    }

                    else if (item.Name == "ModifierName")
                    {
                        var val = header?.UserName;
                        item.SetValue(entity, val);
                    }
                }
            }
            var r = _unitOfWork.DbConnection.Update<T>(entity, dbTransaction == null ? _unitOfWork.DbTransaction : dbTransaction);
            return r;
        }

        /// <summary>
        /// 修改（异步）
        /// </summary>
        /// <param name="entity"></param>
        /// <param name="dbTransaction"></param>
        /// <returns></returns>
        public async Task<bool> UpdateAsync(T entity, IDbTransaction dbTransaction = null)
        {
            var baseEntity = entity.GetType().GetProperties();
            var accountInfo = _accessor.HttpContext.Request.Headers["AccountInfo"].ToString();//.FindFirst(ClaimTypes.NameIdentifier)?.Value;
            accountInfo = HttpUtility.UrlDecode(accountInfo);
            var header = JsonConvert.DeserializeObject<CustomHeader>(accountInfo);
            foreach (var item in baseEntity)
            {
                if (item.Name == "ModifierId")
                {
                    var val = header?.Id;
                    item.SetValue(entity, val);
                }
                else if (item.Name == "ModifyTime")
                {
                    var val = DateTime.Now;
                    item.SetValue(entity, val);
                }

                else if (item.Name == "ModifierName")
                {
                    var val = header?.UserName;
                    item.SetValue(entity, val);
                }
            }
            var r = await _unitOfWork.DbConnection.UpdateAsync<T>(entity, dbTransaction == null ? _unitOfWork.DbTransaction : dbTransaction).ConfigureAwait(false);
            return r;
        }
        #endregion
    }
}
